/*
 * Funny Language - a free style programming language.
 * Copyright (C) 2015 by fanguangping (fanguangping@163.com)
 * ds.h
 */

#ifndef DS_H_
#define DS_H_

#include <stdio.h>
#include "../../ds/datastructure.h"

#ifdef TRUE
#undef TRUE
#endif
#define TRUE 1

#ifdef FALSE
#undef FALSE
#endif
#define FALSE 0

/*
Basic types hierarchy:

-Object
  -Class
  -Atom
    -Boolean
    -Number
      -Complex
        -Real
          -Decimal
          -Fraction
          -Integer
    -Character
    -String
  -Symbol
    -Syntax
  	-Property
  -Vector
  -Environment
  -Procedure
    -Closure
    -Continuation
    -Method
    -Constructor
  -Exception
  -Pair
    -Promise
 * */

#define UNKNOWN_NAME       "[UNKNOWN]"
#define UNKNOWN_TYPE       "[UNKNOWN]"
#define PRIMITIVE_OBJECT        "PrimitiveObject"
#define PRIMITIVE_BOOLEAN       "PrimitiveBoolean"
#define PRIMITIVE_INTEGER       "PrimitiveInteger"
#define PRIMITIVE_DOUBLE        "PrimitiveDouble"
#define PRIMITIVE_CHARACTER     "PrimitiveCharacter"
#define PRIMITIVE_STRING        "PrimitiveString"
#define PRIMITIVE_SYMBOL        "PrimitiveSymbol"
#define PRIMITIVE_PROCEDURE     "PrimitiveProcedure"
#define PRIMITIVE_EXCEPTION     "PrimitiveException"

#define OBJECT_TYPE        "Object"
#define CLASS_TYPE         "Class"
#define ATOM_TYPE          "Atom"
#define PAIR_TYPE          "Pair"
#define BOOLEAN_TYPE       "Boolean" //primitive
#define INTEGER_TYPE       "Integer" //primitive
#define REAL_TYPE          "Real"
#define FRACTION_TYPE      "Fraction"
#define DECIMAL_TYPE       "Decimal"
#define COMPLEX_TYPE       "Complex"
#define DOUBLE_TYPE        "Double" //primitive
#define NUMBER_TYPE        "Number"
#define CHARACTER_TYPE     "Character" //primitive
#define STRING_TYPE        "String" //primitive
#define SYMBOL_TYPE        "Symbol"
#define SYNTAX_TYPE        "Syntax"
#define PROPERTY_TYPE      "Property"
#define VECTOR_TYPE        "Vector"
#define PROCEDURE_TYPE     "Procedure"
#define EXCEPTION_TYPE     "Exception"
#define METHOD_TYPE        "Method"
#define CONSTRUCTOR_TYPE   "Constructor"

#define CLOSURE_TYPE       "Closure"
#define PROMISE_TYPE       "Promise"
#define CONTINUATION_TYPE  "Continuation"
#define ENVIRONMENT_TYPE   "Environment"

struct _Cell;
struct _Scheme;
// typedef struct _Cell* (*ForeignFunc)(struct _Scheme *, struct _Cell *);
typedef struct _Cell* (*OperatorFunc)(struct _Scheme *);

typedef struct _Pair {
	struct _Cell *_car;
	struct _Cell *_cdr;
} Pair;

typedef struct _Cell {
	unsigned int _flag;  //mark-sweep immutable
	const char *_type;
    const char *_name;
	union {
		long _longValue;
		double _doubleValue;
		char *_string;
		void *_pointer;
		OperatorFunc _op;
		// ForeignFunc _func;
		Pair _pair;
	};
} Cell;

#define CELL_SEGSIZE 5000	 /* # of cells in one segment */
#define CELL_NSEGMENT 100    /* # of segments for cells */
#define PROPERTY_COUNT 461
#define METHOD_COUNT 461
#define CONSTRUCTOR_COUNT 11

typedef struct _Scheme {
	Cell* cellSeg[CELL_NSEGMENT];
	int lastCellSeg;
	Cell* freeCell; /* cell* to top of free cells */
	long freeCellCount; /* # of free cells */

	/* We use 4 registers. */
	// OperatorFunc op;							//当前处理方法
	Cell* op;
	Cell* args; /* register for arguments of function */
	Cell* env;  /* stack register for current environment */
	Cell* code; /* register for current code */
	Cell* obj;  /* register for current object */
	Cell* callStack; /* stack register for next evaluation */
	Cell* returnValue;

	char* input;
	int inputPointer;

	// Cell* objectList; /* cell* to symbol table *///管理所有的符号，确保了所有相同名字的符号是同一个
	Cell* globalObjects; /* cell* to symbol table */
	Cell* symbols; /* cell* to symbol references */
	Cell* globalEnv; /* cell* to global environment */

	Tree* inheritance; /* class hierarchy */
	// Cell* classes; /* class objects */ can find in globalObjects

	int token;						//保持词法分析获取的单词

	/* global cell*s to special symbols */
	//Cell* sym_lambda; /* cell* to syntax lambda */
	//Cell* sym_quote; /* cell* to syntax quote */			//引用    '
	//Cell* sym_feed_to; /* => */							// cond中有用到
	//Cell* sym_colon_hook; /* *colon-hook* */
	//Cell* sym_error_hook; /* *error-hook* */
	//Cell* sym_sharp_hook; /* *sharp-hook* */
	//Cell* sym_this; /* *this* */

} Scheme;

/*
 * 常数
 * */
Cell g_nil;
Cell g_eof;
Cell g_true;
Cell g_false;
void init_constants();

// 特征标记
// #define TYPE_MASK       31		/* 0000000000011111 */	// 5位 可以表示32个类型
//#define T_SYNTAX        4096	/* 0001000000000000 */  // 语法符号
//#define T_IMMUTABLE     8192	/* 0010000000000000 */	// 标记一个cell为不可改变的
//#define T_PRIMITIVE     16384	/* 0100000000000000 */	// 标记一个cell为primitive types

#define REF_IMMUTABLE   16384	/* 0100000000000000 */	// 标记一个cell为不可改变的
#define REF_MARK        32768	/* 1000000000000000 */	/* 仅用于gc */

/*
 * 特征标记函数
 * */
// unsigned int typeflag(Cell* p);
// int types(Cell* p);
int is_atom(Scheme *sc, Cell *p);
int is_immutable(Cell* p);
void set_immutable(Cell* p);
int is_mark(Cell* p);
void set_mark(Cell* p);
void clear_mark(Cell* p);

// 词法标记
#define TOK_EOF     -1				// 输入结束
#define TOK_LPAREN  0				// (
#define TOK_RPAREN  1				// )
#define TOK_DOT     2				// .
#define TOK_ATOM    3				// 原子 （number id symbol ）
#define TOK_QUOTE   4				// '
#define TOK_COMMENT 5				// ;
#define TOK_DQUOTE  6				// "
#define TOK_SHARP   7				// #
#define TOK_SHARP_CONST 8			// #  常量 (例如 #t #f #\a)
#define TOK_VECTOR  9				// #( 数组

#define DELIMITERS  "()\";\f\t\v\n\r "	// 分隔符


/* () is #t in R5RS */ //不为#f的都是true
#define is_true(p)       ((p) != &g_false)
#define is_false(p)      ((p) == &g_false)

/*
 * car/cdr/cons函数
 * */
Cell* car(Cell* p);
Cell* cdr(Cell* p);
Cell* cons(Scheme *sc, Cell* a, Cell* b);
Cell* immutable_cons(Scheme *sc, Cell* a, Cell* b);

#define CAR(p)           ((p)->_pair._car)
#define CDR(p)           ((p)->_pair._cdr)
#define CAAR(p)          CAR(CAR(p))
#define CADR(p)          CAR(CDR(p))
#define CDAR(p)          CDR(CAR(p))
#define CDDR(p)          CDR(CDR(p))

#define caar(p)   car(car(p))
#define cadr(p)   car(cdr(p))
#define cdar(p)   cdr(car(p))
#define cddr(p)   cdr(cdr(p))
#define caaar(p)  car(car(car(p)))
#define caadr(p)  car(car(cdr(p)))
#define cadar(p)  car(cdr(car(p)))
#define caddr(p)  car(cdr(cdr(p)))
#define cdaar(p)  cdr(car(car(p)))
#define cdadr(p)  cdr(car(cdr(p)))
#define cddar(p)  cdr(cdr(car(p)))
#define cdddr(p)  cdr(cdr(cdr(p)))
#define caaaar(p) car(car(car(car(p))))
#define caaadr(p) car(car(car(cdr(p))))
#define caadar(p) car(car(cdr(car(p))))
#define caaddr(p) car(car(cdr(cdr(p))))
#define cadaar(p) car(cdr(car(car(p))))
#define cadadr(p) car(cdr(car(cdr(p))))
#define caddar(p) car(cdr(cdr(car(p))))
#define cadddr(p) car(cdr(cdr(cdr(p))))
#define cdaaar(p) cdr(car(car(car(p))))
#define cdaadr(p) cdr(car(car(cdr(p))))
#define cdadar(p) cdr(car(cdr(car(p))))
#define cdaddr(p) cdr(car(cdr(cdr(p))))
#define cddaar(p) cdr(cdr(car(car(p))))
#define cddadr(p) cdr(cdr(car(cdr(p))))
#define cdddar(p) cdr(cdr(cdr(car(p))))
#define cddddr(p) cdr(cdr(cdr(cdr(p))))

#define first(p)  	car(p)
#define second(p) 	car(cdr(p))
#define third(p)  	car(cdr(cdr(p)))
#define fourth(p) 	car(cdr(cdr(cdr(p))))
#define fifth(p)  	car(cdr(cdr(cdr(cdr(p)))))
#define sixth(p)  	car(cdr(cdr(cdr(cdr(cdr(p))))))
#define seventh(p)  car(cdr(cdr(cdr(cdr(cdr(cdr(p)))))))
#define eighth(p)  	car(cdr(cdr(cdr(cdr(cdr(cdr(cdr(p))))))))
#define ninth(p)  	car(cdr(cdr(cdr(cdr(cdr(cdr(cdr(cdr(p)))))))))
#define tenth(p)  	car(cdr(cdr(cdr(cdr(cdr(cdr(cdr(cdr(cdr(p))))))))))
#define eleventh(p) car(cdr(cdr(cdr(cdr(cdr(cdr(cdr(cdr(cdr(cdr(p)))))))))))
#define twelfth(p)  car(cdr(cdr(cdr(cdr(cdr(cdr(cdr(cdr(cdr(cdr(cdr(p))))))))))))

#define rest(p)   	cdr(p)

#define DEFINE_OPERATOR(_opname)      Cell* cell_op_##_opname; Cell* op_##_opname(Scheme *)
#define INIT_CONSTANTS(_typename)     void init_##_typename##_constants(Scheme *sc)
#define INIT_OPERATORS(_typename)     void init_##_typename##_operators(Scheme *sc)

#endif /* DS_H_ */
